﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace uTorrentJunctions
{
    /// <summary>
    /// Typed class for decoded uTorrent resume.dat / resume_dir
    /// </summary>
    /// 
    static class uTorrentClass
    {
        public struct uTorrentItem
        {
            // Partially implemented
            public String key;
            public DateTime? added_on;
            public String caption;
            public DateTime? completed_on;
            public bool completed;
            public Int64 downloaded;
            public String label;
            public List<String> labels;
            public DateTime? last_seen_complete;
            public DateTime? last_active;
            public Int64 order;
            public String path;
            public String pathpart;
            public bool isFile;
            public Int64 started;
            public List<String> trackers;
            public String tracker;
            public String trackerdomain;
        }
        private static DateTime FromUnixTime(long unixTime)
        {
            // Source: http://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c
            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return epoch.AddSeconds(unixTime);
        }
        public static Dictionary<String, uTorrentItem> GetuTorrentItems(object Decoded)
        {
            // Converts decoded object to uTorrentItem dictionary
            Dictionary<String, uTorrentItem> uTorrentItems = new Dictionary<String, uTorrentItem>();

            if (Decoded == null) { return null; }

            if (Decoded.GetType() == typeof(Dictionary<String, Object>))
            {
                // Root Dictionary
                Dictionary<String, Object> root = (Dictionary<String, Object>)Decoded;

                foreach (KeyValuePair<String, Object> o in root)
                {
                    // Skip non-dictionary items (fileguard, etc.)
                    if (o.Value.GetType() != typeof(Dictionary<String, Object>)) { continue; }

                    // Load up item dictionary
                    Dictionary<String, Object> dict = (Dictionary<String, Object>)o.Value;
                    uTorrentItem item = new uTorrentItem();

                    // key
                    item.key = o.Key;

                    // added_on
                    if (dict.ContainsKey("added_on"))
                    {
                        Int64 added_on = (Int64)dict["added_on"];
                        item.added_on = FromUnixTime(added_on).ToLocalTime();
                    }

                    // caption
                    if (dict.ContainsKey("caption"))
                    {
                        byte[] caption = (byte[])dict["caption"];
                        item.caption = Encoding.UTF8.GetString(caption);
                    }
                    // completed_on
                    if (dict.ContainsKey("completed_on"))
                    {
                        Int64 completed_on = (Int64)dict["completed_on"];
                        if (completed_on == 0)
                        {
                            item.completed_on = null;
                        }
                        else
                        {
                            item.completed_on = FromUnixTime(completed_on).ToLocalTime();
                        }
                        // completed?
                        if (completed_on != 0) { item.completed = true; }
                        else { item.completed = false; }
                    }

                    // downloaded (bytes)
                    if (dict.ContainsKey("downloaded"))
                    {
                        item.downloaded = (Int64)dict["downloaded"];
                    }

                    // label (if key does not exist, the first item in labels will be used)
                    if (dict.ContainsKey("label"))
                    {
                        byte[] label = (byte[])dict["label"];
                        item.label = Encoding.UTF8.GetString(label);
                    }

                    // labels
                    item.labels = new List<String>();
                    if (dict.ContainsKey("labels"))
                    {
                        List<Object> labels = (List<Object>)dict["labels"];

                        foreach (byte[] l in labels)
                        {
                            item.labels.Add(Encoding.UTF8.GetString(l));
                        }
                    }

                    if (item.labels.Count == 0)
                    {
                        // If none, revert to label
                        if (dict.ContainsKey("label"))
                        {
                            item.labels.Add(Encoding.UTF8.GetString((byte[])dict["label"]));
                        }
                        else
                        {
                            item.label = "No Label";
                            item.labels.Add("No Label");
                        }
                    }

                    // last_seen_complete
                    if (dict.ContainsKey("last_seen_complete"))
                    {
                        Int64 last_seen_complete = (Int64)dict["last seen complete"];
                        item.last_seen_complete = FromUnixTime(last_seen_complete).ToLocalTime();
                    }

                    // last_active
                    if (dict.ContainsKey("last_active"))
                    {
                        Int64 last_active = (Int64)dict["last_active"];
                        item.last_active = FromUnixTime(last_active).ToLocalTime();
                    }
                    // order
                    if (dict.ContainsKey("order"))
                    {
                        item.order = (Int64)dict["order"];
                    }

                    // started
                    if (dict.ContainsKey("started"))
                    {
                        item.started = (Int64)dict["started"];
                    }

                    // path:
                    if (dict.ContainsKey("path"))
                    {
                        item.path = Encoding.UTF8.GetString((byte[])dict["path"]);
                        // last folder or file part of path
                        item.pathpart = new System.IO.DirectoryInfo(item.path).Name;
                        // if path refers to a file instead of a folder
                        item.isFile = System.IO.File.Exists(item.path);
                    }

                    // trackers (2 scenarios encountered)
                    if (dict.ContainsKey("trackers"))
                    {
                        item.trackers = new List<String>();
                        List<Object> trackers = (List<Object>)dict["trackers"];
                        if (trackers.First().GetType() == typeof(List<Object>))
                        {
                            // Scenario 1: List containing byte[] list
                            List<Object> trackerslist = (List<Object>)trackers.First();
                            foreach (byte[] t in trackerslist)
                            {
                                item.trackers.Add(Encoding.UTF8.GetString(t));
                            }
                            item.tracker = Encoding.UTF8.GetString((byte[])trackerslist.First());
                        }
                        else
                        {
                            // Scenario 2: Byte[] list
                            foreach (byte[] t in trackers)
                            {
                                item.trackers.Add(Encoding.UTF8.GetString(t));
                            }
                        }
                        // tracker
                        item.tracker = item.trackers.First();
                        // trackerdomain
                        Uri trackerUri = new Uri(item.tracker);
                        item.trackerdomain = trackerUri.Host;
                    }

                    // Done. Add or replace to uTorrentItems
                    uTorrentItems[item.key] = item;
                }
                return uTorrentItems;
            }
            return null;
        }
    }
}
